<html><head><title>Operating Systems Spring 2011; Exercise 3:A Multi-threaded Output Device</title></head>
<body bgcolor="SeaShell">
<img src="threads.jpg"style="float:right;" />
<h1>Operating Systems Spring 2011</h1>
<h1>Exercise 3: A Multi-threaded Output Device</h1>
<blockquote style="font-size:120%"><em>He who holds me by a thread is not strong; the thread is strong.</em>
</br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://en.wikipedia.org/wiki/Antonio_Porchia">Antonio Porchia</a>, <em>Voices</em></blockquote>
<h2>Due Date: 10/4/2011</h2>

<font color="red"><b> Before you start, don't forget to read the
<a href="http://www.cs.huji.ac.il/~os/guidelines.html">course guidelines</a></b>!</font>


<h2>Assignment</h2>
<p>Consider an output device in multi-threaded system that accepts output tasks from several client threads concurrently. Each client thread task comprises of writing a block of data to the output device as a single uninterrupted atomic operation. A trivial implementation is to have a single lock that protects the device, where each client thread gets the lock, performs the operation and then releases the lock. Your task is to implement an efficient non-blocking package, which is delivered in the form of a static library. In other words, you will implement a daemon thread that queues client threads' output tasks requests and write these tasks asynchronously to the device, which is simulated, in this exercise, as an output disk file. </p>

<p>The public interface of your library is given by <a href="outputdevice.h">outputdevice.h</a> and explained below. Obviously, there are few internal functions (and data structures) that you might find necessary to implement. These functions are not visible outside the library; therefore, you are not restricted in their number, signatures, and content as they are part of your private implementation.</p>


<h3><code>int initdevice(char *filename)</code></h3>

<p>The function creates the output file <code>filename</code> if it does not exist and opens the output file for writing (appending if the file exists). This function should be called prior to any other functions as a necessary precondition for their success. </p>
<p>Return values are 0 on success, otherwise -1. </p>

<h3><code>int write2device(char *buffer, int length)</code></h3>

<p>The function writes the input <code>buffer</code> (which is of <code>length</code> size) to the output file. The buffer may be freed once this call returns (You should deal with any memory management issues). Note this is non-blocking package you are required to implement, therefore, you should return ASAP, even if the buffer has not yet been written to the disk.</p>

<p>On success, the function returns a <code>task_id</code> (&gt;= 0), which identifies this write operation. Note that you should reuse <code>task_id</code>s when they become available. On failure, -1 will be returned.</p>

<h3><code>void flush2device(int task_id)</code></h3>

<p>The function blocks until the specified <code>task_id</code> has been written to the file. The <code>task_id</code> is a value that was previously returned by <code>write2device</code> function. In case of error, the function should cause the process to exit (not return -1).</p>

<h3><code>void closedevice()</code></h3>

<p>The function closes the output file and resets the system so that it is possible to call <code>initdevice</code> again. All pending <code>task_id</code>s should be written to the output disk file. Any attempt to write new buffers while the system is shutting down should cause an error. </p>

<h3>Error Messages STDERR</h3>
<table border="1" cellpadding="5"> <tr> <th>Message Error</th> <th>Error Description</th> </tr>
<tr><td>&quot;system error\n&quot;</td> <td>When system call fails </td> </tr>
<tr> <td>&quot;Output device library error\n&quot;</td> <td>The rest</td> </tr> </table>

<h2>Background reading and Resources</h2>

<ol> <li>Carefully read the <a href="http://www.planetoid.org/technical/pthreads/manpages/">pthread</a> man-pages, which grouped into 3 major classes:
<ol> <li><b><i>Thread management:</i></b> Working directly on threads.</li> 
<li><b><i>Mutexes:</i></b> Dealing with synchronization (&quot;mutual exclusion&quot;).</li>
<li><b><i>Condition variables:</i></b> Communication between threads that share a mutex.</li> </ol></li>
<li><a href="http://www.llnl.gov/computing/tutorials/pthreads/">POSIX Threads Programming</a> a good tutorial</li> </ol>


<h2>Submission</h2>
Submit a tar file on-line containing the following:
<ul>
<li>A README file. The README should be structured according to
the <a href="http://www.cs.huji.ac.il/~os/guidelines.html">course
guidelines</a>, and contain an explanation on how and why your library functions
are built the way they are.
</li>
<li>The source files for your implementation of the library.
<li>Your Makefile. Running <i>make</i> with no arguments should generate the
<i>liboutputdevice.a</i> library.</il>
</ul>

<font color="red"><b> Do not change the  <a href="outputdevice.h">header file</a>. Your exercise should work with our version of  <a href="outputdevice.h">outputdevice.h</a>.</b></font>

<h2>Guidelines</h2>
<ul>
<li> This exercise objective is Multi-threaded programming; therefore, make sure you protect all shared resources. You may want to use a multi-processor like <code>river</code> to test your code. You should see a nice interleaving of tasks in the output file without any corruption.
<li> Make sure to check the exit status of all the system calls and pthread calls you use.</li>
<li> Make your code readable (indentation, function names, etc.).</li>
</ul>
</body>
</html>
